package org.ruoyi.interview.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import lombok.RequiredArgsConstructor;
import org.ruoyi.common.satoken.utils.LoginHelper;
import org.ruoyi.interview.service.impl.InterviewQuestionDifficultyUpdater;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.ruoyi.common.core.domain.R;
import org.ruoyi.common.core.utils.MapstructUtils;
import org.ruoyi.common.core.utils.StringUtils;
import org.ruoyi.common.log.annotation.Log;
import org.ruoyi.common.log.enums.BusinessType;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.common.web.core.BaseController;
import org.ruoyi.interview.domain.bo.InterviewQuestionBo;
import org.ruoyi.interview.domain.vo.InterviewQuestionVo;
import org.ruoyi.interview.service.IInterviewQuestionService;
import org.ruoyi.interview.mapper.InterviewQuestionCategoryMapper;

import jakarta.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

// 添加DashScope相关导入
import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.utils.Constants;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import com.alibaba.fastjson2.JSON;

import java.io.IOException;

/**
 * 面试题Controller
 *
 * @author ruoyi
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/interview/question")
public class InterviewQuestionController extends BaseController {

    private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(InterviewQuestionController.class);

    private final IInterviewQuestionService interviewQuestionService;
    private final InterviewQuestionCategoryMapper categoryMapper;

    @Autowired
    private InterviewQuestionDifficultyUpdater difficultyUpdater;

    @Value("${dashscope.api.key:}")
    private String dashScopeApiKey;

    // 用于存储处理任务的临时map
    // private Map<String, ProcessingTask> taskMap = new ConcurrentHashMap<>();

    /**
     * 查询面试题列表
     */
    @SaCheckPermission("interview:question:list")
    @GetMapping("/list")
    public TableDataInfo<InterviewQuestionVo> list(InterviewQuestionBo bo, PageQuery pageQuery) {
        return interviewQuestionService.selectInterviewQuestionList(bo, pageQuery);
    }

    /**
     * 根据父级分类ID查询面试题列表（连表查询）
     */
    @SaCheckPermission("interview:question:list")
    @GetMapping("/listByParentId")
    public TableDataInfo<InterviewQuestionVo> listByParentId(InterviewQuestionBo bo, PageQuery pageQuery) {
        return interviewQuestionService.selectInterviewQuestionListByParentId(bo, pageQuery);
    }

    /**

     * 查询面试题列表(带收藏状态和掌握状态)
     */
    @GetMapping("/listWithStatus")
    public TableDataInfo<InterviewQuestionVo> listWithStatus(
            InterviewQuestionBo bo,
            PageQuery pageQuery) {
        String boAnalysis = bo.getAnalysis();
        bo.setAnalysis(boAnalysis);
        Long userId = LoginHelper.getUserId();
        TableDataInfo<InterviewQuestionVo> interviewQuestionVoTableDataInfo = interviewQuestionService
            .selectInterviewQuestionListWithStatus(bo, pageQuery, userId);
        if (StringUtils.isNotEmpty(boAnalysis)){
            interviewQuestionVoTableDataInfo.getRows().forEach(item -> {
                item.setAnalysis("");
            });
        }
        return interviewQuestionVoTableDataInfo;
    }

    /**
     * 查询用户收藏的面试题列表
     */
    @GetMapping("/favoriteList")
    public TableDataInfo<InterviewQuestionVo> favoriteList(
            @RequestParam Long userId,
            @RequestParam(required = false) Long categoryId,
            InterviewQuestionBo bo,
            PageQuery pageQuery) {
        return interviewQuestionService.selectFavoriteQuestionList(userId, categoryId, bo, pageQuery);
    }

    /**
     * 导出面试题列表
     */
    @SaCheckPermission("interview:question:export")
    @Log(title = "面试题", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(InterviewQuestionBo bo, HttpServletResponse response) {
        List<InterviewQuestionVo> list = interviewQuestionService.selectInterviewQuestionList(bo);
        // ExcelUtil.exportExcel(list, "面试题", InterviewQuestionVo.class, response); // 如需导出功能请取消注释
    }

    /**
     * 获取面试题详细信息
     *
     * @param questionId 面试题主键
     */
    @SaCheckPermission("interview:question:query")
    @GetMapping("/info{questionId}")
    public R<InterviewQuestionVo> getInfo(@PathVariable("questionId") Long questionId) {
        return R.ok(interviewQuestionService.selectInterviewQuestionById(questionId));
    }

    /**
     * 新增面试题
     */
    @SaCheckPermission("interview:question:add")
    @Log(title = "面试题", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    public R<Void> add(@Validated(org.ruoyi.common.core.validate.AddGroup.class) @RequestBody InterviewQuestionBo bo) {
        return toAjax(interviewQuestionService.insertInterviewQuestion(bo) ? 1 : 0);
    }

    /**
     * 更新所有面试题难度
     */
    @PostMapping("/updateDifficultAll")
    public R<Void> updateDifficultAll() {
        try {
            // 异步执行更新任务
            new Thread(() -> {
                try {
                    difficultyUpdater.updateAllQuestionDifficulties();
                } catch (Exception e) {
                    logger.error("更新面试题难度时发生错误", e);
                }
            }).start();

            return R.ok("已开始更新所有面试题的难度等级，请查看日志了解详细进度");
        } catch (Exception e) {
            logger.error("触发更新面试题难度失败", e);
            return R.fail("触发更新失败：" + e.getMessage());
        }
    }

    /**
     * 修改面试题
     */
    @SaCheckPermission("interview:question:edit")
    @Log(title = "面试题", businessType = BusinessType.UPDATE)
    @PutMapping("/update")
    public R<Void> edit(@Validated(org.ruoyi.common.core.validate.EditGroup.class) @RequestBody InterviewQuestionBo bo) {
        return toAjax(interviewQuestionService.updateInterviewQuestion(bo) ? 1 : 0);
    }

    /**
     * 修改面试题状态
     */
    @SaCheckPermission("interview:question:edit")
    @Log(title = "面试题", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public R<Void> changeStatus(@RequestBody InterviewQuestionBo bo) {
        return toAjax(interviewQuestionService.updateQuestionStatus(bo.getQuestionId(), bo.getStatus()) ? 1 : 0);
    }

    /**
     * 删除面试题
     *
     * @param questionIds 面试题主键串
     */
    @SaCheckPermission("interview:question:remove")
    @Log(title = "面试题", businessType = BusinessType.DELETE)
    @DeleteMapping("/delete{questionIds}")
    public R<Void> remove(@PathVariable Long[] questionIds) {
        return toAjax(interviewQuestionService.deleteInterviewQuestionByIds(Arrays.asList(questionIds)) ? 1 : 0);
    }

    /**
     * 通过AI获取更多面试题
     *
     * @param map 包含categoryId和prompt的参数
     * @return AI推荐的面试题列表
     */
    @PostMapping("/getQuestionsByAi")
    public R<List<String>> getQuestionsByAi(@RequestBody Map<String, Object> map) {
        try {
            // 获取参数
            Long categoryId = Long.valueOf(map.get("categoryId").toString());
            String prompt = (String) map.get("prompt");

            // 查询该分类下的所有面试题
            InterviewQuestionBo bo = new InterviewQuestionBo();
            bo.setCategoryId(categoryId);
            List<InterviewQuestionVo> questions = interviewQuestionService.selectInterviewQuestionList(bo);

            // 构建发送给AI的提示词
            StringBuilder promptBuilder = new StringBuilder();
            promptBuilder.append("当前已有面试题：\n");

            if (!questions.isEmpty()) {
                for (int i = 0; i < Math.min(questions.size(), 10); i++) { // 限制发送前10个题目，避免提示词过长
                    promptBuilder.append(questions.get(i).getContent()).append("\n");
                }
            } else {
                promptBuilder.append("无\n");
            }

            promptBuilder.append("\n用户提示词：").append(prompt).append("\n\n");
            promptBuilder.append("请根据用户提示词和当前已有面试题，推荐更多相关的面试频率较高的面试题。");
            promptBuilder.append("只需要返回新增的面试题列表，每个面试题占一行，不要返回其他内容。");
            promptBuilder.append("注意：不要重复返回已有的面试题。");
            promptBuilder.append("请以JSON数组格式返回结果，例如：[\"问题1\",\"问题2\",\"问题3\"]");

            String fullPrompt = promptBuilder.toString();

            // 调用DashScope API发送请求
            if (StringUtils.isBlank(dashScopeApiKey)) {
                return R.fail("DashScope API Key未配置");
            }

            Constants.apiKey = dashScopeApiKey;

            Generation gen = new Generation();
            Message userMessage = Message.builder()
                .role(Role.USER.getValue())
                .content(fullPrompt)
                .build();

            GenerationParam param = GenerationParam.builder()
                .model(Generation.Models.QWEN_MAX)
                .messages(java.util.Collections.singletonList(userMessage))
                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                .build();

            GenerationResult result = gen.call(param);

            // 解析返回结果
            String aiResponse = result.getOutput().getChoices().get(0).getMessage().getContent();

            System.out.println("AI返回结果："+ aiResponse);

            // 尝试解析JSON数组
            List<String> aiQuestions;
            try {
                aiQuestions = JSON.parseArray(aiResponse, String.class);
            } catch (Exception e) {
                // 如果JSON解析失败，按行分割处理
                String[] lines = aiResponse.split("\n");
                aiQuestions = java.util.Arrays.stream(lines)
                    .map(String::trim)
                    .filter(line -> !line.isEmpty())
                    .collect(java.util.stream.Collectors.toList());
            }
            // 转换为InterviewQuestionVo列表
            List<String> resultQuestions = aiQuestions.stream()
                .map(question -> {
                    return question;
                })
                .collect(java.util.stream.Collectors.toList());

            return R.ok(resultQuestions);
        } catch (NoApiKeyException e) {
            logger.error("DashScope API Key缺失", e);
            return R.fail("DashScope API Key缺失: " + e.getMessage());
        } catch (ApiException e) {
            logger.error("调用DashScope API异常", e);
            return R.fail("调用AI服务异常: " + e.getMessage());
        } catch (InputRequiredException e) {
            logger.error("调用DashScope API输入参数错误", e);
            return R.fail("AI服务输入参数错误: " + e.getMessage());
        } catch (Exception e) {
            logger.error("通过AI获取面试题失败", e);
            return R.fail("获取AI推荐面试题失败: " + e.getMessage());
        }
    }

    /**
     * 通过AI补全面试题并入库（流式响应）
     * 建立SSE连接
     *
     * @return 流式响应
     */
    @GetMapping(value = "/completeQuestionsByAiSse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter completeQuestionsByAiSse(
            @RequestParam Long categoryId,
            @RequestParam String questions) {
        SseEmitter emitter = new SseEmitter(0L); // 永不超时

        // 解析题目列表
        List<String> questionList;
        try {
            questionList = JSON.parseArray(questions, String.class);
        } catch (Exception e) {
            try {
                emitter.send(SseEmitter.event().name("error").data("题目列表格式错误"));
            } catch (IOException ioException) {
                logger.error("发送错误信息失败", ioException);
            }
            emitter.complete();
            return emitter;
        }

        // 异步处理
        new Thread(() -> {
            try {
                // 检查API Key
                if (StringUtils.isBlank(dashScopeApiKey)) {
                    emitter.send(SseEmitter.event().name("error").data("DashScope API Key未配置"));
                    emitter.complete();
                    return;
                }

                Constants.apiKey = dashScopeApiKey;

                // 发送开始处理消息
                emitter.send(SseEmitter.event().name("start").data("开始处理" + questionList.size() + "道题目"));

                int index = 0;
                // 遍历题目列表，调用AI补全内容
                for (String questionContent : questionList) {
                    try {
                        index++;
                        // 创建InterviewQuestionBo对象
                        InterviewQuestionBo question = new InterviewQuestionBo();
                        question.setContent(questionContent);
                        question.setType("简答题"); // 默认类型为简答题

                        // 设置分类ID
                        question.setCategoryId(categoryId);

                        // 调用AI补全difficulty和analysis字段
                        completeQuestionWithAi(question, categoryId);

                        // 入库
                        interviewQuestionService.insertInterviewQuestion(question);

                        // 发送处理成功消息
                        Map<String, Object> result = new HashMap<>();
                        result.put("index", index);
                        result.put("total", questionList.size());
                        result.put("content", questionContent);
                        result.put("status", "success");
                        result.put("message", "处理完成并入库");
                        emitter.send(SseEmitter.event().name("progress").data(JSON.toJSONString(result)));
                    } catch (Exception e) {
                        // 发送处理失败消息
                        Map<String, Object> result = new HashMap<>();
                        result.put("index", index);
                        result.put("total", questionList.size());
                        result.put("content", questionContent);
                        result.put("status", "error");
                        result.put("message", "处理失败：" + e.getMessage());
                        emitter.send(SseEmitter.event().name("progress").data(JSON.toJSONString(result)));
                        logger.error("处理题目失败：" + questionContent, e);
                    }
                }

                // 发送处理完成消息
                emitter.send(SseEmitter.event().name("finish").data("所有题目处理完成"));
                emitter.complete();
            } catch (Exception e) {
                try {
                    emitter.send(SseEmitter.event().name("error").data("处理过程中发生错误：" + e.getMessage()));
                } catch (IOException ioException) {
                    logger.error("SSE发送错误信息失败", ioException);
                }
                emitter.complete();
                logger.error("通过AI补全面试题失败", e);
            }
        }).start();

        return emitter;
    }

    /**
     * 通过ai生成面试题答案，并返回（流式响应）
     *
     * @param map 包含面试题内容的参数
     */
    @PostMapping(value = "/generateAnalysisSse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter generateAnalysis(@RequestBody Map<String, Object> map) {
        SseEmitter emitter = new SseEmitter(0L); // 永不超时

        // 异步处理
        new Thread(() -> {
            try {
                // 获取参数
                String content = (String) map.get("content");

                // 参数校验
                if (StringUtils.isBlank(content)) {
                    try {
                        emitter.send(SseEmitter.event().name("error").data("面试题内容不能为空"));
                    } catch (IOException e) {
                        logger.error("发送SSE消息失败", e);
                    }
                    emitter.complete();
                    return;
                }

                // 检查API Key
                if (StringUtils.isBlank(dashScopeApiKey)) {
                    try {
                        emitter.send(SseEmitter.event().name("error").data("DashScope API Key未配置"));
                    } catch (IOException e) {
                        logger.error("发送SSE消息失败", e);
                    }
                    emitter.complete();
                    return;
                }

                Constants.apiKey = dashScopeApiKey;

                // 构建发送给AI的提示词
                StringBuilder promptBuilder = new StringBuilder();
                promptBuilder.append("你是一个专业的面试官，请为以下面试题提供详细的解答：\n\n");
                promptBuilder.append("题目：").append(content).append("\n");

                promptBuilder.append("\n请使用以下格式提供详细解答，包括：\n");
                promptBuilder.append("1. 核心知识点解析\n");
                promptBuilder.append("2. 解题思路和步骤\n");
                promptBuilder.append("3. 相关示例代码（如适用）\n");
                promptBuilder.append("4. 注意事项和扩展知识\n");
                promptBuilder.append("请逐步生成内容，我会实时显示给用户。\n");

                String fullPrompt = promptBuilder.toString();

                // 调用DashScope API发送请求（启用流式输出）
                Generation gen = new Generation();
                Message userMessage = Message.builder()
                    .role(Role.USER.getValue())
                    .content(fullPrompt)
                    .build();

                GenerationParam param = GenerationParam.builder()
                    .model(Generation.Models.QWEN_MAX)
                    .messages(java.util.Collections.singletonList(userMessage))
                    .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                    .incrementalOutput(true) // 启用流式输出
                    .build();

                // 流式处理返回结果
                StringBuilder fullResponse = new StringBuilder();

                // 使用RxJava处理流式响应
                gen.streamCall(param)
                    .doOnNext(result -> {
                        String chunkText = result.getOutput().getChoices().get(0).getMessage().getContent();
                        if (chunkText != null && !chunkText.isEmpty()) {
                            fullResponse.append(chunkText);
                            try {
                                // 发送每个文本块到客户端
                                emitter.send(SseEmitter.event().name("content").data(chunkText));
                            } catch (IOException e) {
                                logger.error("发送SSE消息失败", e);
                            }
                        }
                    })
                    .doOnComplete(() -> {
                        try {
                            // 发送处理完成消息
                            emitter.send(SseEmitter.event().name("finish").data(fullResponse.toString()));
                            emitter.complete();
                        } catch (IOException e) {
                            logger.error("发送完成消息失败", e);
                        }
                    })
                    .doOnError(throwable -> {
                        try {
                            logger.error("流式调用出错", throwable);
                            emitter.send(SseEmitter.event().name("error").data("生成答案失败: " + throwable.getMessage()));
                            emitter.complete();
                        } catch (IOException e) {
                            logger.error("发送错误消息失败", e);
                        }
                    })
                    .subscribe();
            } catch (NoApiKeyException e) {
                logger.error("DashScope API Key缺失", e);
                try {
                    emitter.send(SseEmitter.event().name("error").data("DashScope API Key缺失: " + e.getMessage()));
                } catch (IOException ioException) {
                    logger.error("SSE发送错误信息失败", ioException);
                }
                emitter.complete();
            } catch (ApiException e) {
                logger.error("调用DashScope API异常", e);
                try {
                    emitter.send(SseEmitter.event().name("error").data("调用AI服务异常: " + e.getMessage()));
                } catch (IOException ioException) {
                    logger.error("SSE发送错误信息失败", ioException);
                }
                emitter.complete();
            } catch (Exception e) {
                logger.error("通过AI生成面试题答案失败", e);
                try {
                    emitter.send(SseEmitter.event().name("error").data("生成答案失败: " + e.getMessage()));
                } catch (IOException ioException) {
                    logger.error("SSE发送错误信息失败", ioException);
                }
                emitter.complete();
            }
        }).start();

        return emitter;
    }

    /**
     * 提交需要处理的题目列表
     *
     * @param map 包含categoryId和questions的参数
     * @return 任务ID
     */
    /* @PostMapping("/submitQuestionsForAiCompletion")
    public R<String> submitQuestionsForAiCompletion(@RequestBody Map<String, Object> map) {
        try {
            Long categoryId = Long.valueOf(map.get("categoryId").toString());
            List<String> questions = (List<String>) map.get("questions");

            // 生成任务ID
            String taskId = java.util.UUID.randomUUID().toString();

            // 存储任务
            taskMap.put(taskId, new ProcessingTask(categoryId, questions));

            // 返回任务ID
            Map<String, Object> result = new HashMap<>();
            result.put("taskId", taskId);
            result.put("categoryId", categoryId);
            return R.ok(result);
        } catch (Exception e) {
            logger.error("提交题目失败", e);
            return R.fail("提交题目失败: " + e.getMessage());
        }
    } */

    /**
     * 处理任务类
     */
    /* private static class ProcessingTask {
        private Long categoryId;
        private List<String> questions;

        public ProcessingTask(Long categoryId, List<String> questions) {
            this.categoryId = categoryId;
            this.questions = questions;
        }

        public Long getCategoryId() {
            return categoryId;
        }

        public List<String> getQuestions() {
            return questions;
        }
    } */

    /**
     * 调用AI补全单个面试题的内容
     *
     * @param question 面试题对象
     * @param categoryId 分类ID
     * @throws NoApiKeyException
     * @throws ApiException
     * @throws InputRequiredException
     */
    private void completeQuestionWithAi(InterviewQuestionBo question, Long categoryId) throws NoApiKeyException, ApiException, InputRequiredException {
        // 查询分类信息作为上下文
        String categoryPath = "未知分类";
        try {
            List<String> categoryNames = new ArrayList<>();
            Long currentCategoryId = categoryId;

            // 向上遍历获取完整的分类路径
            while (currentCategoryId != null && currentCategoryId > 0) {
                org.ruoyi.interview.domain.InterviewQuestionCategory category =
                    categoryMapper.selectById(currentCategoryId);
                if (category == null) {
                    break;
                }
                categoryNames.add(0, category.getCategoryName()); // 添加到列表开头
                currentCategoryId = category.getParentId();
            }

            if (!categoryNames.isEmpty()) {
                categoryPath = String.join(" > ", categoryNames);
            }
        } catch (Exception e) {
            logger.warn("获取分类信息失败", e);
        }

        // 构建发送给AI的提示词
        StringBuilder promptBuilder = new StringBuilder();
        promptBuilder.append("你是一个专业的面试题专家，当前正在处理【").append(categoryPath).append("】分类下的面试题。\n\n");
        promptBuilder.append("请根据以下面试题内容，补全这道题的难度等级和解析：\n\n");
        promptBuilder.append("题目：").append(question.getContent()).append("\n");
        promptBuilder.append("类型：").append(question.getType()).append("\n");
        promptBuilder.append("所属分类：").append(categoryPath).append("\n\n");
        promptBuilder.append("请以JSON格式返回结果，包含以下字段：\n");
        promptBuilder.append("1. difficulty: 难度等级，只能是\"简单\"、\"中等\"、\"困难\"其中之一\n");
        promptBuilder.append("2. analysis: 使用``````````详细解释题目的答案和相关知识点，也可添加代码示例，如有数学公式也请返回。\n\n");
        promptBuilder.append("示例格式：\n");
        promptBuilder.append("{\n");
        promptBuilder.append("  \"difficulty\": \"中等\",\n");
        promptBuilder.append("  \"analysis\": \"题目解析...\"\n");
        promptBuilder.append("}\n\n");
        promptBuilder.append("注意：只返回JSON，不要包含其他内容。");

        String fullPrompt = promptBuilder.toString();

        logger.info("发送给AI的提示词：" + fullPrompt);

        // 调用DashScope API发送请求
        Generation gen = new Generation();
        Message userMessage = Message.builder()
            .role(Role.USER.getValue())
            .content(fullPrompt)
            .build();

        GenerationParam param = GenerationParam.builder()
            .model(Generation.Models.QWEN_MAX)
            .messages(java.util.Collections.singletonList(userMessage))
            .resultFormat(GenerationParam.ResultFormat.MESSAGE)
            .build();

        GenerationResult result = gen.call(param);

        // 解析返回结果
        String aiResponse = result.getOutput().getChoices().get(0).getMessage().getContent();
        logger.info("AI返回结果：" + aiResponse);

        try {
            // 解析JSON
            Map<String, String> resultMap = JSON.parseObject(aiResponse, Map.class);
            question.setDifficulty(resultMap.get("difficulty"));
            question.setAnalysis(resultMap.get("analysis"));
        } catch (Exception e) {
            logger.error("解析AI返回结果失败", e);
            // 设置默认值
            question.setDifficulty("中等");
            question.setAnalysis("暂无解析");
        }
    }
}
